package daemon_connect;

use strict;
use cldb;
use clstatdb;
use C_client2;

$daemon_connect::error_msg=undef;

sub error {
	return $daemon_connect::error_msg;
}

sub new {
my $self={};
my $class=shift;
my %args=@_;

	#################################################################
	# Validated expected arguments are present, and abort if not.	#
	#################################################################

	$daemon_connect::error_msg=undef;
	if(!exists($args{host}) || !exists($args{daemon})) {
		$daemon_connect::error_msg="Missing mandatory arguments.";
		return undef;
	}
	$args{validate}=0 if !exists($args{validate});
	$args{timeout}=10 if !exists($args{timeout});
	$args{configdb}="$::ENV{TRUECL_CFG}/config.db" if !exists($args{configdb});

	#################################################################
	# Validate the daemon is one that is known.			#
	#################################################################

	if($args{daemon} !~ /^lha_/) {
		$args{daemon}="lha_" . $args{daemon};
	}
	if($args{daemon} !~ /d$/) {
		$args{daemon}.="d";
	}
	my $x=$args{daemon};
	my $node=$args{host};
	my @D=qw(lha_clusterd lha_statd lha_lockd lha_netd lha_hbd lha_mond);
	if(! scalar(grep {/^$x$/} @D)) {
		$daemon_connect::error_msg="Daemon '$x' is unknown.";
		return undef;
	}

	#################################################################
	# We have a valid daemon, so get the port and list of IP	#
	# addresses for it.						#
	#################################################################

	my ($error_rc,$error_msg);
	my $db=new cldb($args{configdb});
	if(!defined($db)) {
		($error_rc,$error_msg)=cldb::error;
		$daemon_connect::error_msg="Unable to open database: $error_msg";
		return undef;
	}

	my $href=$db->get_rows("SELECT number FROM ports WHERE detail = '$x';");
	if(!defined($href) || !defined($href->[0])) {
		$daemon_connect::error_msg="Port not found for '$x' in config database.";
		$db->disconnect;
		return undef;
	}

	$self->{configdb}=$args{configdb};
	$self->{node}=$node;
	$self->{port}=$href->[0]->{number};
	$self->{daemon}=$x;
	$self->{timeout}=$args{timeout};

	$href=$db->get_rows("SELECT ips FROM nodes WHERE name = '$node';");
	if(!defined($href) || !defined($href->[0])) {
		$daemon_connect::error_msg="Node '$node' not found in config database.";
		$db->disconnect;
		return undef;
	}

	$self->{ips}=$href->[0]->{ips};
	$db->disconnect;
	$db=undef;

	#################################################################
	# Have all the necessary information to attempt a connection,	#
	# so do so now.							#
	#################################################################

	my $cli=new C_client2(SERVER_NAME => $node, SERVER_INET => $self->{ips},
				SERVER_PORT => $self->{port}, PKI => $::PKI);

	if(!defined($cli)) {
		$daemon_connect::error_msg="Daemon '$x' not running on '$node.'";
		return undef;
	}
	$self->{connection}=$cli;
	$cli->set_params(TIMEOUT => $args{timeout});
	bless($self,$class);
	if($args{validate}) {
		my $r=validate_running($self);
		if(!$r) {
			return undef;
		}
	}
	return $self;
}

sub validate_running {
my $self=shift;
my %args=@_;

	#################################################################
	# Send the daemon a PING request and if get a response we know	#
	# it is still running.						#
	#################################################################
	$daemon_connect::error_msg=undef;
	my $cli=$self->{connection};
	my ($resp,$err)=$cli->send_request("PING");
	if(!defined($resp)) {
		$daemon_connect::error_msg=$err;
		return 0;
	} else {
		return 1;
	}
}

#########################################################################
# Send a request to the specified daemon. It is possible to override	#
# the default timeout using the TIMEOUT arg. MSG is the message to	#
# send. If no response is expected/required, set ONEWAY to 1.		#
# Returns:								#
# (-1,msg)	- Failed - see msg.					#
# (0,resp)	- Ok - resp is set if ONEWAY not set.			#
#########################################################################

sub send_request {
my $self=shift;
my %args=@_;
my $resp="";
my $err="";

	if(!exists($args{MSG}) || !defined($args{MSG})) {
		return(-1,"Mandatory MSG argument not sent, or not defined.");
	}
	my $msg=$args{MSG};
	delete $args{MSG};
	my $timeout=3;
	my $oneway=0;
	if(exists($args{ONEWAY}) && defined($args{ONEWAY})) {
		$oneway=$args{ONEWAY};
		delete $args{ONEWAY};
	}
	if(exists($args{TIMEOUT}) && defined($args{TIMEOUT})) {
		$timeout=$args{TIMEOUT};
		delete $args{TIMEOUT};
	}
	if(%args) {
		return(-1,"Unexpected arguments found: " . join(",",keys(%args)));
	}

	$daemon_connect::error_msg=undef;
	my $cli=$self->{connection};
	$cli->set_params(TIMEOUT => $timeout);
	($resp,$err)=$cli->send_request($msg,$oneway);
	if(!defined($resp)) {
		$daemon_connect::error_msg=$err;
		return(-1,$err);
	}
	return(0,undef) if $oneway;
	if(!defined($resp)) {
		$daemon_connect::error_msg=$err;
		return (-1,$err);
	}
	return(0,$resp);
}

1;

